package com.lqk.java8.streamAPI2;


import com.lqk.java8.optional.Employee;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;

/**
 * 一 stream的三个操作步骤
 * 1. 创建Stream
 * 2. 中间操作
 * 3. 终止操作(终端操作)
 */
public class StreamAPI2 {
    List<Employee> emps= Arrays.asList(
            new Employee("001", "张三", 18, 9999),
            new Employee("002", "李四", 29, 8888),
            new Employee("003", "王二", 36, 10000),
            new Employee("004", "麻子", 38, 12000),
            new Employee("004", "麻子", 38, 12000),
            new Employee("004", "麻子", 38, 12000)
    );

    //中间操作
    /**
     * 筛选与切片
     *      filter--接收Lambda, 从流中排除某些元素
     *      limit--截断流, 使其元素不超过给定数量
     *      skip(n)--跳过元素, 返回一个扔掉前n个元素的流, 若流中元素不足n个, 则返回一个空流, 与limit(n)互补
     *      distinct--筛选, 通过流所生成元素的hashCode() 和 equals() 去重元素
     */
    //filter
    //内部迭代: 迭代操作由Stream API完成
    @Test
    public void test1(){
        emps.stream()
                .filter((emp)->emp.getAge()>35)    //中间操作: 不会执行任何操作
                .forEach(System.out::println);  //终止操作: 一次性执行全部内容, 即"惰性求值"
    }
    //外部迭代
    @Test
    public void test2(){
        Iterator<Employee> iterator = emps.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }

    //limit
    @Test
    public void test3(){
        emps.stream()
                .filter((e)->e.getSalary()>9000)
                .limit(2)
                .forEach(System.out::println);
    }

    //skip 跳过元素
    @Test
    public void test4(){
        emps.stream()
                .filter((e)->e.getAge()>18)
                .skip(2)
                .forEach(System.out::println);
    }

    //distinct 去重
    @Test
    public void test5(){
        emps.stream()
                .filter((e)->e.getSalary()>9000)
                .distinct()     //必须重写hashCode和equals方法
                .forEach(System.out::println);
    }
    /**
     * 映射
     *      map--接收Lambda, 将元素转换成其他形式或提取信息, 接收一个函数作为参数, 该函数会被应用到每个元素上, 并将其映射成一个新的元素
     *      flatMap--接收一个函数作为参数, 将流中的每个值都换成另一个流, 然后把所有流连接成一个流
     */
    @Test
    public void test6(){
        List<String> list=Arrays.asList("aaa","bbb","ccc","ddd","eee");
        list.stream()
                .map((str)->str.toUpperCase())
                .forEach(System.out::println);
        System.out.println("---------------------------");
        emps.stream()
                .map(Employee::getName)
                .forEach(System.out::println);
        System.out.println("---------------------------");
        Stream<Stream<Character>> streamStream = list.stream()
                .map(StreamAPI2::filterCharacter);
        streamStream.forEach((sm)->{
            sm.forEach(System.out::println);
        });
        System.out.println("---------------------------");
        list.stream()
                .flatMap(StreamAPI2::filterCharacter)
                .forEach(System.out::println);

    }

    //将字符串中的字符提取出来, 转换成流
    public static Stream<Character> filterCharacter(String str){
        List<Character> list=new ArrayList<>();
        for (Character ch:str.toCharArray()){
            list.add(ch);
        }
        return list.stream();
    }
    /**
     * 排序
     *      sorted()--自然排序  (Comparable)
     *      sorted(Compartor com)--定制排序 (Comparator)
     */
    @Test
    public void test7(){
        List<String> list=Arrays.asList("ccc","aaa","ddd","bbb","eee");
        list.stream()
                .sorted()
                .forEach(System.out::println);
        System.out.println("---------------------------");

        emps.stream()
                .sorted((e1,e2)->{
                    if (e1.getAge().equals(e2.getAge())){
                        return e1.getName().compareTo(e2.getName());
                    }else {
                        return e1.getAge().compareTo(e2.getAge());
                    }
                })
                .forEach(System.out::println);
    }
}
